home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 19 / CU Amiga Magazine's Super CD-ROM 19 (1998)(EMAP Images)(GB)[!][issue 1998-02].iso / CUCD / Programming / LEDA / source / src / plane / _circle.c next >
Encoding:
C/C++ Source or Header  |  1994-11-16  |  4.2 KB  |  170 lines

  1. /*******************************************************************************
  2. +
  3. +  LEDA  3.1c
  4. +
  5. +
  6. +  _circle.c
  7. +
  8. +
  9. +  Copyright (c) 1994  by  Max-Planck-Institut fuer Informatik
  10. +  Im Stadtwald, 6600 Saarbruecken, FRG     
  11. +  All rights reserved.
  12. *******************************************************************************/
  13.  
  14.  
  15.  
  16. #include <LEDA/circle.h>
  17. #include <math.h>
  18.  
  19. static const double eps = 1e-10;
  20.  
  21. //------------------------------------------------------------------------------
  22. // circles
  23. //------------------------------------------------------------------------------
  24.  
  25.  
  26. circle::circle()                        { PTR = new circle_rep; }
  27. circle::circle(const point& c, double r)       { PTR = new circle_rep(c,r); }
  28. circle::circle(double x, double y, double r)  
  29.                                         { PTR = new circle_rep(point(x,y),r); }
  30.   
  31.  
  32. int circle::operator==(const circle& c)  const
  33. { double dr =  fabs(ptr()->radius - c.ptr()->radius);
  34.   return (ptr()->center == c.ptr()->center && dr < eps);
  35.  }
  36.  
  37.  
  38. double circle::distance(const point& p) const
  39. { double d = p.distance(ptr()->center);
  40.   return (d - ptr()->radius);
  41.  }
  42.  
  43. double circle::distance(const line& l) const
  44. { double d = l.distance(ptr()->center);
  45.   return (d - ptr()->radius);
  46.  }
  47.  
  48. double circle::distance(const circle& c) const
  49. { double d = ptr()->center.distance(c.ptr()->center);
  50.   return (d - ptr()->radius - c.ptr()->radius);
  51.  }
  52.  
  53. bool circle::inside(const point& p) const 
  54. { return distance(p)<=0; }
  55.  
  56.  
  57. circle circle::translate(double alpha, double d) const
  58. { point p = ptr()->center.translate(alpha,d);
  59.   return circle(p,ptr()->radius);
  60.  }
  61.  
  62. circle circle::translate(const vector& v) const
  63. { point p = ptr()->center.translate(v);
  64.   return circle(p,ptr()->radius);
  65.  }
  66.  
  67. circle  circle::rotate(const point& o, double alpha) const
  68. { return circle(ptr()->center.rotate(o,alpha),ptr()->radius); 
  69.  }
  70.  
  71. circle  circle::rotate(double alpha)          const
  72. { return rotate(point(0,0),alpha);
  73.  }
  74.  
  75. list<point> circle::intersection(const line& l) const
  76. { list<point> result;
  77.   segment s = l.perpendicular(ptr()->center);
  78.   double  d = s.length();
  79.   double  r = ptr()->radius;
  80.   point   F = s.end();
  81.  
  82.   if (d==r) result.append(F);
  83.   
  84.   if (d < r)
  85.   { double alpha = l.angle();
  86.     double x = sqrt(r*r - d*d);
  87.     point  p = F.translate(alpha,x);
  88.     point  q = F.translate(alpha,-x);
  89.     result.append(q);
  90.     result.append(p);
  91.   }
  92.  
  93.   return result;
  94. }
  95.  
  96.  
  97. list<point> circle::intersection(const segment& s) const
  98. { list<point> result,L;
  99.  
  100.   L = intersection(line(s));
  101.  
  102.   point p;
  103.   double  d  = s.length();
  104.  
  105.   forall(p,L)
  106.   { double d1 = s.ptr()->start.distance(p);
  107.     double d2 = s.ptr()->end.distance(p);
  108.     if (d1 <= d && d2 <= d) result.append(p);
  109.    }
  110.  
  111.   return result;
  112. }
  113.  
  114. list<point> circle::intersection(const circle& c) const
  115. { list<point> result;
  116.   segment s(ptr()->center, c.ptr()->center);
  117.   double d  = s.length();
  118.   double r1 = ptr()->radius;
  119.   double r2 = c.ptr()->radius;
  120.  
  121.   if (d > (r1+r2) || (d+r2) < r1 || (d+r1) < r2) return result;
  122.  
  123.  
  124.   double x = (d*d + r1*r1 - r2*r2)/(2*d);
  125.   double alpha = acos(x/r1);
  126.   double beta  = s.angle() + alpha;
  127.   double gamma = s.angle() - alpha;
  128.  
  129.   result.append(ptr()->center.translate(beta,r1));
  130.   if (alpha!=0) result.append(ptr()->center.translate(gamma,r1));
  131.  
  132.   return result;
  133.  }
  134.  
  135.  
  136. segment circle::left_tangent(const point& p) const
  137. { if (inside(p)) error_handler(1,"left_tangent:: point inside circle");
  138.   segment s(p,ptr()->center);
  139.   double d = s.length();
  140.   double alpha = asin(ptr()->radius/d) + s.angle();
  141.   point touch = p.translate(alpha,sqrt(d*d - ptr()->radius*ptr()->radius));
  142.   return segment(p,touch);
  143. }
  144.  
  145. segment circle::right_tangent(const point& p) const
  146. { if (inside(p)) error_handler(1,"right_tangent:: point inside circle");
  147.   segment s(p,ptr()->center);
  148.   double d = s.length();
  149.   double alpha = s.angle() - asin(ptr()->radius/d);
  150.   point touch = p.translate(alpha,sqrt(d*d - ptr()->radius*ptr()->radius));
  151.   return segment(p,touch);
  152. }
  153.  
  154. ostream& operator<<(ostream& out, const circle& c) 
  155. { out << c.center() << " "<< c.radius(); 
  156.   return out;
  157.  } 
  158.  
  159. istream& operator>>(istream& in,  circle& c) 
  160. { point cent;
  161.   double rad;
  162.   if (in) in >> cent;
  163.   if (in) in >> rad;
  164.   c = circle(cent,rad);
  165.   return in;
  166. }
  167.  
  168.  
  169.